'use client'

import React, {useEffect, useRef, useState} from 'react';
import * as THREE from "three";
import {FBXLoader} from "three/examples/jsm/loaders/FBXLoader.js";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js";
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js';
import {AnimationClip} from "three";
import {LAppWavFileHandler} from "@/app/lib/live2d/lappwavfilehandler";
import {CharacterManager} from "@/app/lib/character";
import {LAppPal} from "@/app/lib/live2d/lapppal";

export default function Live3d() {
    const [loadingProgress, setLoadingProgress] = useState(0);
    const [isLoading, setIsLoading] = useState(true);
    const canvasRef = useRef<HTMLDivElement>(null);
    const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
    const sceneRef = useRef<THREE.Scene | null>(null);
    const cameraRef = useRef<THREE.PerspectiveCamera | null>(null);
    const mixerRef = useRef<THREE.AnimationMixer | null>(null);
    const animationActionsRef = useRef<{ [key: string]: THREE.AnimationAction }>({});
    const clockRef = useRef<THREE.Clock | null>(null);
    const shapeRef = useRef<THREE.Mesh | null>(null);
    const animationIdRef = useRef<number | null>(null);
    const currentActionRef = useRef<THREE.AnimationAction>(null);
    const [isListeningToMic, setIsListeningToMic] = useState(true);


    useEffect(() => {
        if (!canvasRef.current) return;

        const scene = new THREE.Scene();
        sceneRef.current = scene;
        scene.background = new THREE.Color(0x999999);

        const axesHelper = new THREE.AxesHelper(1000);
        scene.add(axesHelper);

        const camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 2000);
        cameraRef.current = camera;
        camera.position.set(0, -20, 480);
        camera.lookAt(scene.position);
        scene.add(camera);

        const renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
        rendererRef.current = renderer;
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setPixelRatio(window.devicePixelRatio);
        canvasRef.current.appendChild(renderer.domElement);

        const controls = new OrbitControls(camera, renderer.domElement);
        controls.target.set(0, 0, 0);
        controls.update();


        const gui = new GUI();
        gui.domElement.style.right = '0px';
        gui.domElement.style.width = '300px';

        const ambientLight = new THREE.AmbientLight(0xffffff, 1.66);
        scene.add(ambientLight);
        gui.add(ambientLight, 'intensity', 0, 3).name('环境光');

        const lightPos = [
            [0, 0, 10, 0.3], //前
            [0, 0, -10, 0.7], //后
            [0, 10, 0, 0.6], //上
            [0, -10, 0, 0.2], //下
            [-10, 0, 0, 0.3], //左
            [10, 0, 0, 0.3], //右
            [5, 10, 0, 0.1],
            [-5, 10, 0, 0.1],
            [0, 10, 5, 0.1],
            [0, 10, -5, 0.1],
        ];

        lightPos.forEach(([x, y, z, intensity]) => {
            const directionalLight = new THREE.DirectionalLight(0xffffff, intensity);
            directionalLight.position.set(x, y, z);
            scene.add(directionalLight);
            // 参数2表示平行光.position附近方框的尺寸
            // const dirHelper = new THREE.DirectionalLightHelper(directionalLight, 20);
            // scene.add(dirHelper);
            //
            // gui.add(directionalLight, 'intensity', 0, 2).name('平行光强度').onChange(function () {
            //     dirHelper.update();
            // });
            //
            // gui.add(directionalLight.position, 'x', 0, 30).name('平行光X轴').onChange(function () {
            //     dirHelper.update();
            // });
            //
            // gui.add(directionalLight.position, 'y', 0, 30).name('平行光Y轴').onChange(function () {
            //     dirHelper.update();
            // });

        });

        clockRef.current = new THREE.Clock();

        const textureLoader = new THREE.TextureLoader();

        //添加地面
        const floorPlaneGeometry = new THREE.PlaneGeometry(2000, 2000); // 地面尺寸
        const floorTexture = textureLoader.load('/images/floor.jpg');
        const floorPlaneMaterial = new THREE.MeshLambertMaterial({
            map: floorTexture,
        });
        const floorMesh = new THREE.Mesh(floorPlaneGeometry, floorPlaneMaterial);
        floorMesh.rotation.x = -Math.PI / 2; // 旋转平面使其水平
        floorMesh.position.y = -100; // 将平面稍微降低一点以避免重叠
        scene.add(floorMesh);

        // 创建带曲度的墙面
        const width = 2000;
        const height = 875;
        const divisions = 100;
        const wallPlaneGeometry = new THREE.PlaneGeometry(width, height, divisions, divisions);

        // 修改顶点位置以形成弯曲
        const positions = wallPlaneGeometry.attributes.position.array;
        for (let i = 0; i < positions.length; i += 3) {
            const x = positions[i];
            // 控制弯曲程度
            positions[i + 2] = -Math.cos(x / width * Math.PI) * 200; // 控制弯曲程度
        }
        const wallTexture = textureLoader.load('/images/bg.jpg');
        const wallPlaneMaterial = new THREE.MeshLambertMaterial({
            map: wallTexture,
        })
        const wallMesh = new THREE.Mesh(wallPlaneGeometry, wallPlaneMaterial);
        wallMesh.position.y = 320
        scene.add(wallMesh);


        const fbxLoader = new FBXLoader();

        fbxLoader.load("./审点心.fbx", (fbx: THREE.Group<THREE.Object3DEventMap>) => {
            console.log("fbx加载成功", fbx);
            fbx.position.set(0, -100, 200);
            // fbx.rotation.y = -Math.PI / 2;
            fbx.scale.set(0.2, 0.2, 0.2);
            fbx.traverse((child: THREE.Object3D<THREE.Object3DEventMap>) => {
                if (child instanceof THREE.Mesh) {
                    if (child.isMesh) {
                        const materials = Array.isArray(child.material) ? child.material : [child.material];
                        materials.forEach((material: THREE.MeshStandardMaterial) => {
                            if (material.name === '材质.075') {
                                console.log("加载眼睛材质");
                                material.emissiveIntensity = 1;
                                material.emissiveMap = textureLoader.load('textures/eye.png');
                            }

                            if (material.name === '材质.074') {
                                console.log("加载身体材质");
                                material.metalness = 1;
                                material.map = textureLoader.load('textures/color.png');
                            }
                        });
                    }
                    // 假设你的模型动画是形态键动画，把当前模型作为形状模型复制给shapeModel
                    if (child.morphTargetInfluences && child.morphTargetDictionary) {
                        console.log("------------------------形状模型--------------------------")
                        shapeRef.current = child as THREE.Mesh;
                    }
                }
            });

            scene.add(fbx);
            mixerRef.current = new THREE.AnimationMixer(fbx);

            fbx.animations.forEach((clip: AnimationClip) => {
                console.log('动画剪辑名:', clip.name);
                animationActionsRef.current[clip.name] = mixerRef.current.clipAction(clip);

            });
            setIsLoading(false);
            console.log("------------------------开始眨眼--------------------------")
            //初始睁眼动画
            blinkAnimate();
        }, (xhr: { loaded: number; total: number; }) => {
            const progress = (xhr.loaded / xhr.total) * 100;
            setLoadingProgress(Math.round(progress));
        }, (error: any) => {
            console.error('An error happened', error);
            setIsLoading(false);
        });

        const wavFileHandler = LAppWavFileHandler.getInstance();
        const animate = () => {

            if (mixerRef.current && clockRef.current) {
                mixerRef.current.update(clockRef.current.getDelta());
            }
            // 时间更新
            LAppPal.updateTime();
            const deltaTimeSeconds: number = LAppPal.getDeltaTime();
            if (!wavFileHandler.update(deltaTimeSeconds)) {
                // 只有在监听麦克风时才检查新的音频数据
                let talkData = CharacterManager.getInstance().popAudioQueue();
                if (talkData) {
                    wavFileHandler.start(talkData);
                    playAnimation('wave'); // 在 TTS 播放期间播放挥手动画
                }
                if (wavFileHandler.getPlayStatus()) {
                    stopAnimation()
                }
            }

            renderer.render(scene, camera);
            requestAnimationFrame(animate);
        };

        // 在开始动画循环之前，初始化 LAppPal 的时间
        LAppPal.updateTime();
        // 启动动画循环
        requestAnimationFrame(animate);

        const handleResize = () => {
            if (cameraRef.current && rendererRef.current) {
                cameraRef.current.aspect = window.innerWidth / window.innerHeight;
                cameraRef.current.updateProjectionMatrix();
                rendererRef.current.setSize(window.innerWidth, window.innerHeight);
            }
        };

        window.addEventListener('resize', handleResize);


        return () => {
            window.removeEventListener('resize', handleResize);
            if (rendererRef.current && rendererRef.current.domElement && rendererRef.current.domElement.parentNode) {
                rendererRef.current.domElement.parentNode.removeChild(rendererRef.current.domElement);
            }
            gui.destroy();
        };

    }, []);


    const blinkConfig = useRef({
        progress: 0,
        direction: 1,
        speed: 0.12,
        threshold: 0.9,
        minInterval: 1000,
        maxInterval: 3000,
        nextTime: 0,
        keyIndex: -1
    });

    // 缓动函数，使眨眼更自然
    function easeInOutQuad(t: number) {
        return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
    }

    function blinkAnimate() {
        const timestamp = performance.now();
        const config = blinkConfig.current;

        if (!shapeRef.current || config.keyIndex === -1) {
            if (shapeRef.current && shapeRef.current.morphTargetDictionary) {
                config.keyIndex = shapeRef.current.morphTargetDictionary['blink'] || 0;
            } else {
                requestAnimationFrame(blinkAnimate);
                return;
            }
        }

        if (timestamp >= config.nextTime) {
            config.progress += config.direction * config.speed;

            if (config.progress >= config.threshold) {
                config.direction = -1;
            } else if (config.progress <= 0) {
                config.direction = 1;
                config.progress = 0;
                config.nextTime = timestamp + Math.random() * (config.maxInterval - config.minInterval) + config.minInterval;
            }

            const easedProgress = easeInOutQuad(config.progress / config.threshold);
            shapeRef.current.morphTargetInfluences[config.keyIndex] = easedProgress * config.threshold;

            // Add some randomness to make it more natural
            if (Math.random() < 0.1) {
                config.progress = Math.max(0, config.progress - 0.1);
            }
        }

        rendererRef.current?.render(sceneRef.current, cameraRef.current);
        requestAnimationFrame(blinkAnimate);
    }


    function playAnimation(animationName: string) {
        // 停止当前正在播放的动画
        if (currentActionRef.current) {
            currentActionRef.current.stop();
        }
        // 播放指定的动画
        currentActionRef.current = animationActionsRef.current[animationName];
        if (currentActionRef.current) {
            currentActionRef.current.play();
        } else {
            console.warn(`Animation "${animationName}" not found.`);
        }
    }


    function playLoopAnimation(animationName: string) {
        if (currentActionRef.current) {
            currentActionRef.current.stop();
        }
        currentActionRef.current = animationActionsRef.current[animationName];
        if (currentActionRef.current) {
            // 修改：设置动画为无限循环
            currentActionRef.current.reset().setLoop(THREE.LoopRepeat, Infinity).play();
        } else {
            console.warn(`未找到动画 "${animationName}"`);
        }
    }


    function stopAnimation() {
        // 停止当前正在播放的动画
        if (currentActionRef.current) {
            currentActionRef.current.stop();
        }
        if (animationIdRef.current) {
            cancelAnimationFrame(animationIdRef.current)
            animationIdRef.current = null;
        }
        // console.info(`Animation Stop.`);
    }


    return (
        <div className="absolute top-0 left-0 w-full h-full bg-center bg-cover z-0">
            {isLoading && (
                <div className="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
                    <p className="text-white mt-4">{`加载进度：${loadingProgress}%`}</p>
                </div>
            )}
            <div
                ref={canvasRef}
                className="absolute top-0 left-0 w-full h-full bg-center bg-cover z-0"
            />
        </div>
    );
}